
import serial
import logging
import pprint
from ezcrc16 import verifyLen
from ezcrc16 import verifyCRC
from ezcrc16 import crc16ccitt



logging.basicConfig()
#logging.getLogger('ssh.transport').setLevel(logging.INFO)
pp = pprint.PrettyPrinter(indent=4)



# Constants
SER_TIMEOUT=2
SYN = "\x16"







class Dongle:

  def __init__(self, name):
    self.ser = serial.Serial(name, baudrate=9600, timeout=SER_TIMEOUT, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, xonxoff=0, rtscts=0)
    print "Port of dongle: "+self.ser.portstr

  def read(self, nb):
    line = self.ser.read(nb)
    return line

  def write(self, line):
    self.ser.write(line)

  def readAndVerifyAck(self):
    line = self.read(6)
    print "ACK len: ",len(line)," line: "+pp.pformat(line)
    if (verifyAck(line)):
      return True
    # end if
    return False
  # end def

  def readAndVerifyAnswer(self, srcMacAddr):
    line = self.read(18)
    print "ANS len: ",len(line)," line: "+pp.pformat(line)
    if (verifyAnswer(line, srcMacAddr)):
      return True
    # end if
    return False
  # end def

  def set_forwarder(self, srcMacAddr, dstMacAddr):
    request = SYN+SYN+"\x10\xE0"+dstMacAddr+"\x00\x0F"
    request = request+"\x34\x12"; # CRC16
    pp.pprint(request)
    (hi,lo) = crc16ccitt(request[2:])
    print pp.pformat(request[2:]), " -> ", hi,lo
    request += chr(hi) # CRC16
    request += chr(lo) # CRC16
    print "Sending request "+pp.pformat(request)+" ..."
    self.write(request)
    print "Waiting ACK ..."
    if (self.readAndVerifyAck()):
      print "Waiting answer ..."
      return self.readAndVerifyAnswer(srcMacAddr)

    return False
  # end def


  
# 16 16 04 FF CF 3B 16 16 10 E0 DE 00 00 00 10 E3 0C D7 49 0F 34 12 11 5A


### Generic




### Answer

def verifyAnswer(line, srcMacAddr):
  if (verifyLen(line, 18)):
    if (verifyCRC(line[2:])):
      if (verifyAnswerStart(line)):
        mac = line[4:12]
        if (verifyMacAddr(mac, srcMacAddr)):
          answer = line[12:18]
          print "Answer:"+pp.pformat(answer)
          rssi = answer[0]
          channel = answer[1]
          loPanId = answer[2]
          hiPanId = answer[3]
          print "ANS OK: RSSI="+str(ord(rssi))+",CHAN="+str(ord(channel))+",LOPAN="+str(ord(loPanId))+",HIPAN="+str(ord(hiPanId))
          return True
        # end if
      # end if
    # end if
  # end if
  return False
# end def

def verifyAnswerStart(line):
  if (line[0] == SYN
      and line[1] == SYN
      and line[2] == '\x10'
      and line[3] == '\xE0'):
    print "ANS SYN OK"
    return True
  # end if
  return False
# end def


def verifyMacAddr(act, srcMac):
  print "Exp MAC:"+pp.pformat(srcMac)
  print "Act MAC:"+pp.pformat(act)
  if (act == srcMac):
    print "MAC OK"
    return True
  # end if
  return False




### ACK  
def verifyAck(line):
  if (verifyLen(line, 6)):
    if (verifyCRC(line[2:])):
      if (verifyAckStart(line)):
        return True
    # end if
  # end if
  return False
# end def

def verifyAckStart(line):
  if (line[0] == SYN
      and line[1] == SYN
      and line[2] == '\x04'
      and line[3] == '\xFF'
      and line[4] == '\xCF'
      and line[5] == '\x3B'):
    print "ACK SYN OK"
    return True
  # end if
  return False
# end def
  

 



    

### ARCHIVES ###
def temp():
  print "Init"

  request = ""
  request += chr(SYN)
  request += chr(SYN)
  request += chr(0x10)
  request += chr(0xE0)
  request += chr(0xD7)
  request += chr(0x01)
  request += chr(0x00)
  request += chr(0x00)
  request += chr(0x70)
  request += chr(0xE3)
  request += chr(0x0C)
  request += chr(0xD7)
  request += chr(0x00)
  request += chr(0x0F)
  request += chr(0x34)
  request += chr(0x12)
  print "A:"+hex2str(request)
  c16i = acrc16.xmodem(request)
  print "B:"+str(c16i)
  #print "CRC16_CCITT:"+str(c16i)+" / 1:"+str(int2hex(c16i)[1])+" 0:"+str(int2hex(c16i)[0])
  request += (int2hex(c16i)[1])
  request += (int2hex(c16i)[0])
  print "B:"+hex2str(request)

  #exit(0)

  print "Begin"

  #16 16 10 E0 D7 01 00 00 70 E3 0C D7 00 0F 34 12 C1 9D
  request = bytearray((SYN,SYN,0x10,0xE0,0xD7,0x01,0x00,0x00,0x70,0xE3,0x0C,0xD7,0x00,0x0F,0x34,0x12,0xC1,0x9D))
  print hex2str(request)


  ser = serial.Serial('/dev/ttyUSB0', baudrate=9600, timeout=5, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, xonxoff=0, rtscts=0)
  print ser.portstr
  ser.flowControl(1)
  ser.setDTR(1)
  ser.setRTS(1)

  print "Sending request "+hex2str(request)+" ..."
  ser.write(request)
  print "Waiting answer ..."
  line = ser.readline()
  print "len",len(line)
  decoded = hex2str(line)
  print decoded

  ser.close()             # close port



  pp.pprint(request)


#\x16\x16\x10\xE0\xD7\x01\x00\x00\x70\xE3\x0C\xD7\x00\x0F\x34\x12\xC1\x9D
